package com.qhx.rtkcloud.ntrip;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketOption;
import java.net.SocketOptions;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.*;

//@Configuration
public class GgaSocket {


    @Value("${rtk.tcp.portList}")
    public List<Integer> portList;

    public static ExecutorService executorService = Executors.newFixedThreadPool(20);

    public static Map<String, Socket> clientMap = new ConcurrentHashMap<>();

    public static Map<Socket, LinkedBlockingQueue<byte[]>> mapQueue = new ConcurrentHashMap<>();

    @Bean
    public void createSocket() {
        for (Integer port : portList) {
            try {
                ServerSocket serverSocket = new ServerSocket(port);
                GgaSocketQueue ggaSocketQueue = new GgaSocketQueue(serverSocket);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    public void createSocket(int port, ServerSocket serverSocket) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Socket socket = serverSocket.accept();
                        receiveData(socket, port);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    public void receiveData(Socket socket, Integer port) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                byte[] buffer = new byte[10240];
                InputStream inputStream = null;
                try {
                    inputStream = socket.getInputStream();
                    while (true) {
                        int read = inputStream.read(buffer);
                        if (read > 0) {
                            byte[] bytes1 = Arrays.copyOfRange(buffer, 0, read);
                            String gpggaSentence = new String(bytes1, StandardCharsets.UTF_8);
                            //从本地客户端连接
                            if (gpggaSentence.equals("localClient")) {
                                if (clientMap.containsKey(String.valueOf(port))) {
                                    inputStream.close();
                                    socket.close();
                                    break;
                                }
                                clientMap.put(String.valueOf(port), socket);
                                mapQueue.put(socket, new LinkedBlockingQueue<byte[]>());
                                getMessage(socket, String.valueOf(port));
                                break;
                            } else {
                                Socket clientSocket = clientMap.get(String.valueOf(port));
                                if (clientSocket != null && !clientSocket.isClosed()) {
                                    LinkedBlockingQueue<byte[]> queue = mapQueue.get(clientSocket);
                                    queue.offer(bytes1);
                                    mapQueue.put(clientSocket, queue);
                                    buffer = new byte[10240];
                                }
                            }
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void getMessage(Socket socket, String port) {
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                OutputStream outputStream = null;
                try {
                    outputStream = socket.getOutputStream();
                    LinkedBlockingQueue<byte[]> deque = mapQueue.get(socket);
                    while (true) {
                        byte[] bytes = deque.take();
                        String message = new String(bytes, StandardCharsets.UTF_8);
                        System.out.println(message);
                        /*try {
                            socket.sendUrgentData(0xff);
                        } catch (IOException e) {
                            mapQueue.remove(socket);
                            clientMap.remove(port);
                            break;
                        }*/
                        if (bytes != null) {
                            outputStream.write(bytes);
                            outputStream.flush();
                        }

                    }
                } catch (IOException | InterruptedException e) {
                    mapQueue.remove(socket);
                    clientMap.remove(port);
                    e.printStackTrace();
                }

            }
        });
    }


}
